package com.bright.ghj.overt.web.controller;

import com.bright.ghj.common.pojo.bo.RestResult;
import com.bright.ghj.overt.util.SecurityUtil;
import com.bright.ghj.common.util.StringUtil;
import com.bright.ghj.overt.constant.DataConstant;
import com.bright.ghj.overt.pojo.command.ImportAccessCommand;
import com.bright.ghj.overt.pojo.dto.AttachedDTO;
import com.bright.ghj.overt.pojo.dto.ExportExcelDTO;
import com.bright.ghj.overt.pojo.dto.ImportExcelDTO;
import com.bright.ghj.overt.pojo.query.TableDataIdQuery;
import com.bright.ghj.overt.pojo.vo.AsyncTaskResultVO;
import com.bright.ghj.overt.pojo.vo.SaveFileResultVO;
import com.bright.ghj.overt.pojo.vo.SaveResultVO;
import com.bright.ghj.overt.pojo.vo.TableTypeVO;
import com.bright.ghj.overt.service.AccessImportService;
import com.bright.ghj.overt.service.BaseDataService;
import com.bright.ghj.overt.service.NavigateService;
import com.bright.ghj.overt.service.StoreFileService;
import com.bright.ghj.common.util.FileUtil;
import com.bright.ghj.common.util.ListUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.NoSuchFileException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author hxj
 * @Date 2024/2/18 10:46
 * @Description 上传文件 包括导入
 */
@RequestMapping("/upload")
@RestController
@RequiredArgsConstructor
@Slf4j
@Api(tags = "文件操作接口")
public class UploadController {

    private final BaseDataService baseDataService;
    private final NavigateService navigateService;
//    private final MQProduceService mqProduceService;
    @Qualifier("asyncAccessImport")
//    @Qualifier("MQAccessImport")
    private final AccessImportService<AsyncTaskResultVO> accessImportService;
//    private final ObjectMapper objectMapper;

//    @Qualifier("fileSystemStoreFile")
//    @Qualifier("mongoDBStoreFile")
    private final StoreFileService storeFileService;

    private final DataConstant dataConstant;

    /**
     * 导出excel模板
     * @param exportExcelDTO 查询
     */
    @ApiOperation(value = "导出excel模板")
    @GetMapping("/exportExcelTemplate/{id}")
    public void exportExcelTemplate(ExportExcelDTO exportExcelDTO, HttpServletResponse response) {
        try {
            baseDataService.exportExcelByTemplate(exportExcelDTO, response, true);
        } catch (NoSuchFileException | FileNotFoundException e) {
            log.error("导出失败，模板文件未找到：", e);
            throw new RuntimeException("导出失败，模板文件未找到");
        } catch (Exception e) {
            log.error("导出失败：", e);
            throw new RuntimeException("导出失败：" + e.getMessage());
        }
    }

    /**
     * 导出excel
     * @param exportExcelDTO 查询
     */
    @ApiOperation(value = "导出excel")
    @GetMapping("/exportExcel/{id}")
    public void exportExcel(ExportExcelDTO exportExcelDTO, HttpServletResponse response) {
        try {
//            baseDataService.exportExcelByTemplate(exportExcelDTO, response, false);
            baseDataService.exportExcel(exportExcelDTO, response);
        } catch (NoSuchFileException | FileNotFoundException e) {
//            try {
//                response.setCharacterEncoding("utf-8");
//                response.getWriter().write("导出失败，模板文件未找到：" + e.getMessage());
//            } catch (IOException ex) {
//                throw new RuntimeException(ex);
//            }
            log.error("导出失败，模板文件未找到：", e);
            throw new RuntimeException("导出失败，模板文件未找到");
        } catch (Exception e) {
//            try {
//                response.setCharacterEncoding("utf-8");
//                response.getWriter().write("导出失败：" + e.getMessage());
//                e.printStackTrace();
//            } catch (IOException ex) {
//                throw new RuntimeException(ex);
//            }
            log.error("导出失败：", e);
            throw new RuntimeException("导出失败：" + e.getMessage());
        }
    }

    @PreAuthorize("hasAnyAuthority('cwgkEdit','dwgkEdit','swgkEdit')")
    @ApiOperation(value = "excel导入")
    @PostMapping(value = "/importExcel")
    public RestResult importExcel(ImportExcelDTO importExcelDTO, MultipartFile importExcelFile) {
//        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
//        String format = simpleDateFormat.format(new Date());
//
//        String path = ClassUtils.getDefaultClassLoader().getResource("static/uploads/excel/").getPath();
//        File file = new File(path + format);
//        if (!file.exists()) {
//            file.mkdirs();
//        }

        String oldFileName = importExcelFile.getOriginalFilename();
        // 校验上传的文件类型 不能是xls  xlsx以外的文件类型
        String fileType;
        try {
            fileType = FileUtil.getFileTypeByInputStream(importExcelFile.getInputStream(), oldFileName);
            log.debug(oldFileName + " 文件类型：" + fileType);
        } catch (Exception e) {
            e.printStackTrace();
            return RestResult.fail("识别失败：" + e.getMessage());
        }
        if (!StringUtil.equals(fileType, "xls") && !StringUtil.equals(fileType, "xlsx")) {
            return RestResult.fail("上传的文件类型错误！" + oldFileName);
        }

        // Excel不需要上传到MongoDB 上传了也没记录fileId
//        List<MultipartFile> multipartFiles = new ArrayList<>();
//        multipartFiles.add(importExcelFile);
//        List<SaveFileResultVO> saveFileResultVOS;
//        try {
//            saveFileResultVOS = storeFileService.saveFile(multipartFiles, "excel/");
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }

        SaveResultVO importExcelVO;
//        if (saveFileResultVOS.size() > 0) {
//            SaveFileResultVO saveFileResultVO = saveFileResultVOS.get(0);
//            String newFileName = "" + saveFileResultVO.getUploadPath() + saveFileResultVO.getNewFileName();


            try {
//                importExcelVO = baseDataService.importExcel(importExcelDTO, new File(newFileName));
                importExcelVO = baseDataService.importExcelNew(importExcelDTO, importExcelFile);
            } catch (IOException e) {
                e.printStackTrace();
                return RestResult.fail("上传失败：" + e.getMessage());
            }
//        }

        return RestResult.success(importExcelVO);
    }

    @PreAuthorize("hasAnyAuthority('cwgkEdit','dwgkEdit','swgkEdit')")
    @ApiOperation(value = "access导入")
    @PostMapping(value = "/importAccess")
    public RestResult importAccess(ImportAccessCommand importAccessCommand, MultipartFile importAccessFile) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
        String format = simpleDateFormat.format(new Date());

        String path = ClassUtils.getDefaultClassLoader().getResource("static/uploads/access/").getPath();
        File parentFile = new File(path + format);
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }

        String oldFileName = importAccessFile.getOriginalFilename();
        // TODO 校验上传的文件类型 不能是bj以外的文件类型
        if (!StringUtil.endsWith(oldFileName, ".bj")) {
            return RestResult.fail("上传的文件类型错误！后缀名只能为.bj！" + oldFileName);
        }

        String username = getUserName();
        importAccessCommand.setUserName(username);
        String uuid = UUID.randomUUID().toString();
        String newFileName = username + "_" + uuid + "_" + oldFileName;
        File newFile = new File(parentFile, newFileName);

        try {
            importAccessFile.transferTo(newFile);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // 设置需要导入的表 如果未传 则获取全部的表类型
        if (importAccessCommand.getTableNames() == null || importAccessCommand.getTableNames().length == 0) {
            List<TableTypeVO> tableTypeVOS = navigateService.listTableTypesByMenuId(dataConstant.CW_CATEGORY);
            List<String> tableNames = ListUtil.toSingleList(tableTypeVOS, TableTypeVO::getTableName);
            importAccessCommand.setTableNames(tableNames.toArray(new String[0]));
        }

        List<AsyncTaskResultVO> asyncTaskResultVOS;
        try {
//            importExcelVO = baseDataService.importAccess(importAccessCommand, newFile);
            asyncTaskResultVOS = accessImportService.startImport(importAccessCommand, newFile, username);

        } catch (Exception e) {
            e.printStackTrace();
            return RestResult.fail("上传失败：" + e.getMessage());
        }

        return RestResult.success(asyncTaskResultVOS);
    }

    @ApiOperation(value = "查看附件")
    @GetMapping(value = "/attached/view/{id}")
    public RestResult viewAttached(TableDataIdQuery tableDataIdQuery) {
        return RestResult.success(baseDataService.viewAttachedFiles(tableDataIdQuery));
    }

    @PreAuthorize("hasAnyAuthority('cwgkEdit','dwgkEdit','swgkEdit')")
    @ApiOperation(value = "附件上传")
    @PostMapping(value = "/attached/send")
    public RestResult sendAttached(TableDataIdQuery tableDataIdQuery, List<MultipartFile> importFiles) {
//        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
//        String format = simpleDateFormat.format(new Date());
//
//        String path = ClassUtils.getDefaultClassLoader().getResource("static/uploads/userFiles/").getPath();
//        File file = new File(path + format);
//        if (!file.exists()) {
//            file.mkdirs();
//        }
        List<String> fileTypeSuffixList = new ArrayList<>();

        for (MultipartFile importFile : importFiles) {
            String oldFileName = importFile.getOriginalFilename();
            // 校验上传的文件类型
            String fileTypeSuffix = null;
            try {
                fileTypeSuffix = FileUtil.getFileTypeByInputStream(importFile.getInputStream(), oldFileName);
//                System.out.println(oldFileName + " 文件类型：" + fileTypeSuffix);
                fileTypeSuffixList.add(fileTypeSuffix);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (fileTypeSuffix == null || !isFileTypeAllowed(fileTypeSuffix)) {
                return RestResult.fail("上传失败，不允许上传的文件类型！" + (fileTypeSuffix == null ? "" : fileTypeSuffix));
            }
        }

//            String username = getUserName();
//            String uuid = UUID.randomUUID().toString();
//            String newFileName = username + "_" + uuid + "_" + oldFileName;
//            File newFile = new File(file, newFileName);

        List<SaveFileResultVO> saveFileResultVOS;
        try {
            // 兼容如MongoDB上传的模式
//                importFile.transferTo(newFile);
            saveFileResultVOS = storeFileService.saveFile(importFiles, "userFiles/");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        List<AttachedDTO> attachedDTOS = new ArrayList<>();
        int i = 0;
        for (SaveFileResultVO saveFileResultVO : saveFileResultVOS) {
            AttachedDTO attachedDTO = new AttachedDTO();
//            attachedDTO.setUploadPath("uploads/userFiles/" + file.getName() + "/");//"uploads/userFiles/" +
//            attachedDTO.setNewFileName(newFileName);
            attachedDTO.setUploadPath(saveFileResultVO.getUploadPath());
            attachedDTO.setNewFileName(saveFileResultVO.getNewFileName());
            attachedDTO.setUserName(getUserName());
            attachedDTO.setOldFileName(saveFileResultVO.getOldFileName());
            attachedDTO.setSuffix(fileTypeSuffixList.get(i));
            attachedDTOS.add(attachedDTO);
            i++;
        }

        // 保存进附件数据表
        baseDataService.saveAttachedFiles(attachedDTOS, tableDataIdQuery);

        return RestResult.success();
    }

    @PreAuthorize("hasAnyAuthority('cwgkEdit','dwgkEdit','swgkEdit')")
    @ApiOperation(value = "删除附件")
    @GetMapping(value = "/attached/delete/{deleteIds}")
    public RestResult deleteAttached(@PathVariable String deleteIds) {
        List<Integer> attachedList = new ArrayList<>();
        for (String attachedId : StringUtil.split(deleteIds, ",")) {
            attachedList.add(Integer.parseInt(attachedId));
        }
        baseDataService.deleteAttachedData(attachedList);
        return RestResult.success();
    }


    // 获取当前登录用户姓名
    private String getUserName() {
        return SecurityUtil.getLoginUser().getUsername();
    }

    private static boolean isFileTypeAllowed(String fileType) {
        boolean result = FileUtil.FILE_TYPE_MAP.containsKey(fileType);
        if (!result) {
            List<String> officeFileType = Arrays.asList("doc", "docx", "xls", "xlsx", "ppt", "pptx");
            return officeFileType.contains(fileType);
        }
        return true;
    }

}
